package com.gitee.wsl.mathematics.function.scale.discrete.banded

import com.gitee.wsl.mathematics.interpolator.Percent

/**
 * Represents domain as band (for barchart for example).
 *
 * BandScale.invoke(domain) returns the coordinate of the start of each band.
 *
 *
 * [padding]
 *
 * [paddingInner] representents the size between
 *
 * Band scales are like ordinal scales except the output range is continuous and numeric.
 * Discrete output values are automatically computed by the scale by dividing the continuous range into uniform bands.
 * Band scales are typically used for bar charts with an ordinal or categorical dimension.
 * The unknown value of a band scale is always NaN: they do not allow implicit domain construction.
 */
class BandScale<D> internal constructor() : BandedScale<D>() {

    override var padding: Percent
        get() = Percent(_paddingInner)
        set(value) {
            _paddingInner = value.value
            _paddingOuter = value.value
            rescale()
        }

    /**
     * Sets the inner padding to the specified value which must be in the range [0%, 100%].
     * Returns the current inner padding which defaults to 0%.
     * The inner padding determines the ratio of the range that is reserved for blank space before each band.
     */
     var paddingInner: Percent
        get() = Percent(_paddingInner)
        set(value) {
            _paddingInner = value.coerceToDefault().value
            rescale()
        }

    /**
     * Sets the outer padding to the specified value which must be in the range [0%, 100%].
     * Returns the current outer padding which defaults to 0%.
     * The outer padding determines the ratio of the range that is reserved for blank space before the first
     * band and after the last band.
     */
     var paddingOuter: Percent
        get() = Percent(_paddingOuter)
        set(value) {
            _paddingOuter = value.coerceToDefault().value
            rescale()
        }

    override fun copy(): BandScale<D> {
        return BandScale<D>().also {
            it.align        = align
            it.domain        = domain
            it.range        = range
            it.round        = round
            it.padding      = padding
            it.paddingInner = paddingInner
            it.paddingOuter = paddingOuter
            it.rescale()
        }
    }
}